package com.zbkj.client.task;

import com.alibaba.fastjson.JSON;
import com.zbkj.client.config.WebSocketSessionManager;
import com.zbkj.client.dao.MaterialMapper;
import com.zbkj.client.enums.WebSocketEventType;
import com.zbkj.client.service.AgentClientService;
import com.zbkj.client.service.ClientLoginService;
import com.zbkj.client.service.MaterialService;
import com.zbkj.client.service.impl.VideoServiceCommonImpl;
import com.zbkj.client.utils.FileUtil;
import com.zbkj.common.model.assets.Material;
import com.zbkj.common.model.client.workbench.IntoPieces;
import com.zbkj.common.model.client.workbench.VideoTemplateFinal;
import com.zbkj.common.utils.OssUtil;
import com.zbkj.service.service.IntoPiecesService;
import com.zbkj.service.service.VideoTemplateFinalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class VideoTemplateUpdateStatusTask {

    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private VideoTemplateFinalService videoTemplateFinalService;

    @Autowired
    private VideoServiceCommonImpl videoServiceCommon;

    @Autowired
    private IntoPiecesService intoPiecesService;

    @Autowired
    private MaterialService materialService;

    @Autowired
    private MaterialMapper materialMapper;

    @Autowired
    private WebSocketSessionManager webSocketSessionManager;

    @Value("${workbench.video-split}")
    private String videoSplitBaseUrl;

    @Autowired
    private AgentClientService agentClientService;

    @Autowired
    private ClientLoginService clientLoginService;

    private final String videoTemplateStatusUrl = "/api/v1/video/template/status";

    /**
     * 启动定时任务
     * @param linkId 模板成片任务ID
     */
    public void start(String linkId) {
        schedule(linkId, 0);
    }

    private void schedule(String linkId, int retryCount) {
        long delay = retryCount == 0 ? 2 * 60 * 1000 : 60 * 1000; // 首次2分钟，后续1分钟
        taskScheduler.schedule(() -> {
            try {
                doTask(linkId, retryCount);
            } catch (Exception e) {
                log.error("定时任务-视频模板状态更新异常", e);
            }
        }, new Date(System.currentTimeMillis() + delay));
    }

    private void doTask(String linkId, int retryCount) {
        // 根据linkId获取视频模板记录
        VideoTemplateFinal videoTemplate = videoTemplateFinalService.lambdaQuery()
                .eq(VideoTemplateFinal::getLinkId, linkId)
                .one();
        
        if (videoTemplate == null) {
            log.warn("定时任务-未找到视频模板记录，linkId={}", linkId);
            return;
        }
        
        if (videoTemplate.getIsDel() != null && videoTemplate.getIsDel() == 1) {
            log.info("视频模板已被删除，linkId={}", linkId);
            return;
        }
        
        if (videoTemplate.getStatus() != null && videoTemplate.getStatus() == 2) {
            //扣点
            clientLoginService.updateMerPoint(videoTemplate.getUserId(),
                    videoTemplate.getMerId(),
                    "templateVideo",
                    videoTemplate.getId(),
                    agentClientService.getMouleName("templateVideo"),
                    videoTemplate.getTitle(),
                    agentClientService.getPointByDuration("templateVideo", videoTemplate.getDuration()),
                    videoTemplate.getDuration()
            );

            log.info("定时任务-视频模板已更新过，linkId={}", linkId);
            return;
        }

        Integer id = videoTemplate.getId();
        Integer userId = videoTemplate.getUserId();
        Integer merId = videoTemplate.getMerId();

        // 请求外部视频模板状态接口
        String url = videoSplitBaseUrl + videoTemplateStatusUrl + "/" + linkId;
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<Void> entity = new HttpEntity<>(headers);
        
        try {
            ResponseEntity<Map> response = restTemplate.exchange(url, HttpMethod.GET, entity, Map.class);
            Map<String, Object> respBody = response.getBody();
            
            if (respBody == null) {
                log.warn("视频模板状态接口返回空数据，linkId={}", linkId);
                return;
            }

            // 确定ws事件名称
            String eventName="";

            Boolean success = (Boolean) respBody.get("success");
            if (success != null && success) {
                Map<String, Object> data = (Map<String, Object>) respBody.get("data");
                if (data != null) {
                    Map<String, Object> liveEditingJob = (Map<String, Object>) data.get("LiveEditingJob");
                    if (liveEditingJob != null) {
                        String status = (String) liveEditingJob.get("Status");
                        
                        if ("Success".equals(status)) {
                            // 更新为成功状态
                            videoTemplate.setStatus(2);
                            videoTemplate.setUpdateTime(new Date());
                            videoTemplateFinalService.updateById(videoTemplate);
                            log.info("视频模板生成成功，linkId={}", linkId);

                            //扣点
                            clientLoginService.updateMerPoint(videoTemplate.getUserId(),
                                    videoTemplate.getMerId(),
                                    "templateVideo",
                                    videoTemplate.getId(),
                                    agentClientService.getMouleName("templateVideo"),
                                    videoTemplate.getTitle(),
                                    agentClientService.getPointByDuration("templateVideo", videoTemplate.getDuration()),
                                    videoTemplate.getDuration()
                            );

                            //推送ws事件名称
                            eventName = WebSocketEventType.AddVideoTemplateSuccess.name();
                            videoServiceCommon.pushWsEvent(id, userId, 2, eventName);

                            //成功了就保存到素材或者成片
                            Map<String, Object> saveLocation = videoTemplate.getSaveLocation();
                            if (saveLocation != null) {

                                String sourceUrl = videoTemplate.getOssUrl();
                                String fileTypeLoop = FileUtil.getExtensionWithURI(sourceUrl);
                                String fileName = System.currentTimeMillis() + "." + fileTypeLoop;

                                String newUrl = OssUtil.copyOssFile(sourceUrl, "client", merId,userId, "piece" , fileName);

                                if ("piece".equals(saveLocation.get("module"))){
                                    Integer saveId = insertPiece(videoTemplate, newUrl);
                                    //更新videoTemplate的值
                                    saveLocation.put("id", saveId);
                                    videoTemplate.setSaveLocation(saveLocation);
                                    videoTemplateFinalService.updateById(videoTemplate);
                                } else if ("material".equals(saveLocation.get("module"))){
                                    Integer saveId = insertMaterial(videoTemplate, newUrl);
                                    //更新videoTemplate的值
                                    saveLocation.put("id", saveId);
                                    videoTemplate.setSaveLocation(saveLocation);
                                    videoTemplateFinalService.updateById(videoTemplate);
                                }
                            }
                        } else if (retryCount < 5) {
                            // 继续等待，1分钟后重试
                            log.info("视频模板未完成，1分钟后重试，linkId={}, retry={}", linkId, retryCount + 1);
                            schedule(linkId, retryCount + 1);
                            return;
                        } else {
                            // 超过最大重试次数，标记为失败
                            videoTemplate.setStatus(7);
                            videoTemplate.setErrMsg("超过最大重试次数，任务失败");
                            videoTemplate.setUpdateTime(new Date());
                            videoTemplateFinalService.updateById(videoTemplate);
                            log.warn("视频模板生成超时，linkId={}", linkId);
                            //推送ws事件名称
                            eventName = WebSocketEventType.AddVideoTemplateFail.name();
                            videoServiceCommon.pushWsEvent(id, userId, 7, eventName);
                        }
                    }
                }
            } else {
                // 接口调用失败
                String errMsg = (String) respBody.get("message");
                videoTemplate.setStatus(7);
                videoTemplate.setErrMsg(errMsg != null ? errMsg : "接口调用失败");
                videoTemplate.setUpdateTime(new Date());
                videoTemplateFinalService.updateById(videoTemplate);
                log.error("视频模板生成失败，linkId={}, errMsg={}", linkId, errMsg);
                //推送ws事件名称
                eventName = WebSocketEventType.AddVideoTemplateFail.name();
                videoServiceCommon.pushWsEvent(id, userId, 7, eventName);
            }
        } catch (Exception e) {
            log.error("请求视频模板状态接口异常，linkId={}", linkId, e);
            if (retryCount < 5) {
                schedule(linkId, retryCount + 1);
            } else {
                videoTemplate.setStatus(7);
                videoTemplate.setErrMsg("请求接口异常: " + e.getMessage());
                videoTemplate.setUpdateTime(new Date());
                videoTemplateFinalService.updateById(videoTemplate);

                //推送ws事件
                String eventName = WebSocketEventType.AddVideoTemplateFail.name();
                videoServiceCommon.pushWsEvent(id, userId, 7, eventName);
            }
        }
    }

    private Integer insertPiece(VideoTemplateFinal videoTemplate, String newUrl) {
        IntoPieces intoPieces = new IntoPieces();
        intoPieces.setName(videoTemplate.getTitle());
        intoPieces.setIsFolder(0);
        intoPieces.setUserId(videoTemplate.getUserId());
        intoPieces.setMerId(videoTemplate.getMerId());

        intoPieces.setUrl(newUrl);
        intoPieces.setModule("template");
        intoPieces.setSource("template");
        intoPieces.setFileRealType("video/mp4");
        Integer saveParentId = (Integer) videoTemplate.getSaveLocation().get("parent_id");
        if (saveParentId != null && saveParentId == 0) {
            intoPieces.setCompleteFolder("/");
            intoPieces.setParentId(0);
        }else{
            IntoPieces byId = intoPiecesService.getById(saveParentId);
            intoPieces.setCompleteFolder(byId.getCompleteFolder() + saveParentId + "/");
            intoPieces.setParentId(saveParentId);
        }

        intoPiecesService.save(intoPieces);

        return intoPieces.getId();

    }

    private Integer insertMaterial(VideoTemplateFinal videoTemplate, String newUrl) {
        Material material = new Material();
        material.setName(videoTemplate.getTitle());
        material.setIsFolder(0);
        material.setUserId(videoTemplate.getUserId());
        material.setMerId(videoTemplate.getMerId());

        material.setUrl(newUrl);
        material.setModule("template");
        material.setSource("template");
        material.setFileRealType("video/mp4");
        Integer saveParentId = (Integer) videoTemplate.getSaveLocation().get("parent_id");
        if (saveParentId != null && saveParentId == 0) {
            material.setCompleteFolder("/");
            material.setParentId(0);
        }else{
            Material byId = materialService.getById(saveParentId);
            material.setCompleteFolder(byId.getCompleteFolder() + saveParentId + "/");
            material.setParentId(saveParentId);
        }

        materialMapper.insert(material);
        return material.getId();
    }
} 